
package Lexico;
/**
 *
 * @author Pablo and Ortiz
 */
import java.util.ArrayList;
import javax.swing.JOptionPane;
//import Enumerados.categoriaLexica;


public class AnalizadorLexico {


/* ESTA ES LA IMPLEMENTACION DE NUESTRO ANALIZADOR LEXICO, SE AJUSTA AL AUTOMATA QUE HAY EN LA MEMORIA*/


  public static enum Estado {ESINI, ESIDENT, ESNAT, ESCERO, ESENT, ESREAL, ESIG, ESMEN,
        ESMAY,ESCASTINTER1, ESCASTINTER2, ESNUMINTER1, ESNUMINTER2, ESNUMINTER3,ESREALEXP0, ESDIS, ESSUM, ESRES, ESMULT, ESDIV, ESAND, ESOR, ESMOD, ESNEG,
        ESASIG, ESPARAB, ESPARCER, ESCASTINT,NOREC, ESCASTREAL, ESCS, ESPYC,ESREALDEC,ESREALEXP, ESIN, ESOUT,ESCOMENT , ESEOF, ESIF, ESELSE, ESTHEN,
        ESELSIF,ESENDIF,ESWHILE, ESSOMB, ESCORCHAB, ESCORCHCER, ESPUNTO, ESAMP, ESCOMA};


    private Estado estado;
    private String lexema;
    private ArrayList<Token> tokens;
    private ArrayList errores;
    private char[] buffer;
    private int index;
    private int linea;
    private int columna;

// CONSTRUCTURA DE NUESTRO ANALIZADOR. COMIENZA EN EL ESTADO INICIAL, PONE EL LEXEMA A VACIO,
    //EL INDICE A CERO Y CARGA EN EL BUFFER EL PROGRAMA
	 public AnalizadorLexico (char[] buff){
	        estado = Estado.ESINI;
	        lexema = "";
            linea=1;
            columna=1;
	        this.buffer = buff;
	        index = 0;
            errores=new ArrayList();
	    }


	 public Estado getEstado(){
			return estado;
	}
//LA FUNCION TRANSITA HACE QUE EL ANALIZADOR TRANSITE AL ESTADO QUE SE LE INDIQUE, Y EN CASO DE QUE EL ESTADO SEA
// DIFERENTE DEL INICIAL IR CONCATENANDO CARACTERES DEL BUFFER AL LEXEMA E INCREMENTAR EL INDICE.

    public void transita (Estado estado){
    	this.estado = estado;
    	if (estado != Estado.ESINI ) //mientras no vuelva al estado 0 concatenamos caracteres
    	{
             this.lexema = lexema+buffer[index];
             index++;
         }
    }


/* LA FUNCION SIGTOKEN() DEVUELVE UN ARRAYLIST DE TOKENS CON TODOS LOS TOKENS QUE EL ANALIZADOR LEXICO HA
 * RECONOCIDO EN EL CODIGO QUE LE HEMOS INTRODUCIDO.
 * CONSISTE EN UN BUCLE WHILE SIN CONDICION QUE SOLO PARA CUANDO SE HAYA RECONOCIDO EL FIN DE FICHERO, MIENTRAS
 * TANTO, A TRAVES DE UN SWITCH (CASE) VAMOS VIENDO QUE CARACTERES HAY Y A QUE ESTADO HAY QUE TRANSITAR PARA QUE
 * SE RECONOZCAN LOS TOKENS.
 */
public ArrayList sigToken(){
   try{
     tokens=new ArrayList();
             estado=Estado.ESINI;
             lexema="";
             while (true){
                     switch (estado){
                         case ESINI:
                             if (esTabulador() || esRetornoCarro() || esFinLinea() || esBlanco()){
                                     index++;
                                     if(esFinLinea())
                                         cuentaSaltos();
                                     transita(Estado.ESINI);
                             }
                             else if (esIn()) transita (Estado.ESIN);
                             else if (esOut()) transita (Estado.ESOUT);
                             else if (esLetra() || esGuionBajo()) transita (Estado.ESIDENT);
                             else if (esDigitoPos()) transita (Estado.ESNAT);
                             else if (esCero()) transita (Estado.ESCERO);
                             else if (esPyc()) transita(Estado.ESPYC);
                             else if (esIgual()) transita(Estado.ESASIG);
                             else if (esMayor()) transita(Estado.ESMAY);
                             else if (esMenor()) transita(Estado.ESMEN);
                             else if (esExclamacion()) transita(Estado.ESNEG);
                             else if (esSuma()) transita(Estado.ESSUM);
                             else if (esResta()) transita(Estado.ESRES);
                             else if (esMultiplicacion()) transita(Estado.ESMULT);
                             else if (esDivision()) transita(Estado.ESDIV);
                             else if (esMod()) transita(Estado.ESMOD);
                             else if (esAmp()) transita(Estado.ESAND);
                             else if (esBarra()) transita(Estado.ESOR);
                             else if (esParCerrado()) transita(Estado.ESPARCER);
                             else if (esArroba()) transita(Estado.ESCOMENT);
                             else if (esFinArchivo()) transita(Estado.ESEOF);
                             else if (esParAbierto()) transita(Estado.ESPARAB);
                             else if (esPunto())transita (Estado.ESPUNTO);
                             else if (esCorchAbierto()) transita (Estado.ESCORCHAB);
                             else if (esCorchCerrado()) transita (Estado.ESCORCHCER);
                             else if (esSombrero()) transita (Estado.ESSOMB);
                             else if (esComa()) transita (Estado.ESCOMA);
                             //else if (esAmp()) transita (Estado.ESAMP);

                             /*
                             else if (esIf())transita (Estado.ESIF);
                             else if (esThen())transita (Estado.ESTHEN);
                             else if (esElse())transita (Estado.ESELSE);
                             else if (esElsif()) transita (Estado.ESELSIF);
                             else if (esEndif()) transita (Estado.ESENDIF);
                             else if (esWhile()) transita (Estado.ESWHILE);*/
                             else if(true)
                                 transita(Estado.NOREC);
                             break;

/* CADA UNO DE LOS SIGUIENTES CASOS QUE VIENEN A CONTINUACION SE AJUSTAN AL DISEÑO DEL AUTOMATA QUE LE ADJUNTAMOS
 * EN LA MEMORIA, EN LA CUAL TAMBIEN EXPLICAMOS SU FUNCIONAMIENTO.
 */
                         case ESIDENT:

                             if (esLetra() || esGuionBajo() || esDigito()) transita (Estado.ESIDENT);
                             else if(lexema.equalsIgnoreCase("int")) tokenTent();
                             else if(lexema.equalsIgnoreCase("real")) tokenTreal();
                             else if(lexema.equalsIgnoreCase("if")) tokenIf();
                             else if(lexema.equalsIgnoreCase("then")) tokenThen();
                             else if(lexema.equalsIgnoreCase("else")) tokenElse();
                             else if(lexema.equalsIgnoreCase("elsif")) tokenElsif();
                             else if(lexema.equalsIgnoreCase("endif")) tokenEndif();
                             else if(lexema.equalsIgnoreCase("while")) tokenWhile();
                             else if(lexema.equalsIgnoreCase("do")) tokenDo();
                             else if(lexema.equalsIgnoreCase("endwhile")) tokenEndwhile();
                             else if(lexema.equalsIgnoreCase("tipo")) tokenTipo();
                             else if(lexema.equalsIgnoreCase("pointer")) tokenPointer();
                             else if(lexema.equalsIgnoreCase("rec")) tokenRec();
                             else if(lexema.equalsIgnoreCase("endrec")) tokenEndrec();
                             else if(lexema.equalsIgnoreCase("free")) tokenFree();
                             else if(lexema.equalsIgnoreCase("alloc")) tokenAlloc();
                             else if(lexema.equalsIgnoreCase("fun")) tokenFun();
                             else if(lexema.equalsIgnoreCase("end")) tokenEnd();
                             else if(lexema.equalsIgnoreCase("return")) tokenReturn();
                             else if (lexema.equalsIgnoreCase("returns")) tokenReturns();
                             else if(lexema.equalsIgnoreCase("null")) tokenNull();



                             else    tokenIdent();
                             break;

                         case NOREC:
                            /* errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                             tokenError();*/
                             error();
                             break;


                         case ESCERO:

                             if (esPunto()) transita(Estado.ESNUMINTER1);
                             else if (esDigito()) {//comprobar hasta que sea blanco
                            	/* errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                                 tokenError();*/
                                 error();
                             }
                             else tokenInt();
                             break;

                         case ESNAT:

                             if(esDigito()) transita(Estado.ESNAT);
                             else if(esPunto()) transita(Estado.ESNUMINTER1);
                             else if(esE()) transita(Estado.ESNUMINTER2);
                             else tokenInt();
                             break;

                         case ESREALDEC:

                             if(esE()) transita(Estado.ESNUMINTER2);
                             else if(esCero()) transita(Estado.ESNUMINTER1);
                             else if(esDigitoPos()) transita(Estado.ESREALDEC);
                             else tokenReal();
                             break;

                         case ESREALEXP:

                             if(esDigito()) transita(Estado.ESREALEXP);
                             else tokenReal();
                             break;

                         case ESNUMINTER1:

                             if(esCero())transita(Estado.ESNUMINTER1);
                             else if (esDigitoPos()) transita(Estado.ESREALDEC);
                             else {
                            	 /*errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                            	 tokenError();*/
                                 error();
                             }
                             break;


                         case ESNUMINTER2:

                             if(esResta()) transita(Estado.ESNUMINTER3);
                             else if(esDigitoPos()) transita(Estado.ESREALEXP);
                             else if(esCero()) transita(Estado.ESREALEXP0);
                             else {
                            	 /*errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                            	 tokenError();*/
                                 error();
                             }
                             break;

                         case ESNUMINTER3:

                             if(esDigitoPos()) transita(Estado.ESREALEXP);
                             else if (esCero()) transita(Estado.ESREALEXP0);
                             else {
                            	/* errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                            	 tokenError();*/
                                 error();
                             }
                             break;

                         case ESREALEXP0:

                             if(!esDigito() && !esResta() && !esE() && !esLetra())
                                     tokenReal();
                             else {
                            	/* errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                            	 tokenError();*/
                                 error();
                             }
                             break;

                         case ESPYC:

                             tokenPyc();
                             break;

                         case ESASIG:

                             if(hayIgual()) tokenComp();
                             else tokenAsig();
                             break;

                         case ESMAY:

                             if(hayMayorIgual()) tokenMAYIG();
                             else tokenMayor();
                             break;

                         case ESMEN:

                             if(hayMenorIgual()) tokenMENIG();
                             else tokenMenor();
                             break;

                         case ESNEG:

                             if (hayDist()) tokenDistinto();
                             else tokenNegacion();
                             break;

                         case ESSUM:

                             tokenSuma();
                             break;

                         case ESRES:

                             tokenResta();
                             break;

                         case ESMULT:

                             tokenMultiplicacion();
                             break;

                         case ESDIV:

                             tokenDivision();
                             break;

                         case ESMOD:

                             tokenModulo();
                             break;

                         case ESAND:

                             if(hayAmp())
                                     tokenAndLogico();
                             else  {
                            	/* errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                            	 tokenError();*/
                                 tokenAmpersand();
                             }
                             break;


                         case ESOR:

                             if (hayBarra())
                                     tokenOrLogico();
                             else  {
                            	 /*errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
                            	 tokenError();*/
                                 error();
                             }
                             break;


                         case ESPARCER:
                             //if (esThen()) transita(Estado.ESIDENT);
                             //else
                                if (lexema.contains(" ")) lexema=lexema.replace (" ","");
                                tokenParCerrado();
                             break;

                         case ESPARAB:

                            /*
                             if (hayBlancos()) transita (Estado.ESPARAB);
                             else if(!esIdentInt() && esInt()) transita(Estado.ESCASTINTER1);
                             else if(!esIdentReal() && esReal()) transita(Estado.ESCASTINTER2);
                             
                             else tokenParAbierto();
                             break;*/

                           if (hayBlancos()) transita (Estado.ESPARAB);
                           //if (esLetra()) transita (Estado.KAKA);

                           else if (esInt()){
                               //if (lexema.contains(" "))
                                   lexema=lexema.replace (" ","");
                               if (!sigue()){
                                   transita(Estado.ESCASTINTER1);}
                               else {
                                        if (esBlanco2()&& (esBlanco3()||esParCerrado2())) transita(Estado.ESCASTINTER1);
                                        else{
                                   index=index-2;
                                   
                                   lexema=lexema.replace("i","");
                                   lexema=lexema.replace("n","");
                                   tokenParAbierto();
                                   transita(Estado.ESIDENT);}
                           }
                           }
                  
                           else if (esReal()){
                               lexema=lexema.replace (" ","");
                               if (!sigue())transita(Estado.ESCASTINTER2);
                               else {
                                        if (esBlanco2()&& (esBlanco3()||esParCerrado2())) transita(Estado.ESCASTINTER1);
                                        else {
                                                index=index-3;
                                                lexema=lexema.replace("r","");
                                                lexema=lexema.replace("a","");
                                                lexema=lexema.replace("e","");
                                                tokenParAbierto();
                                                transita(Estado.ESIDENT);
                               }
                           }}
                               
                       
                           else tokenParAbierto();


                           
                           break;

                     

                         case ESCASTINTER1:

                             if (hayBlancos()) transita (Estado.ESCASTINTER1);
                             else if (esParCerrado()) transita (Estado.ESCASTINT);
                             else  transita (Estado.ESIDENT); // ERROR??????? O IDENTIFICADOR???? (inta)
                             break;


                         case ESCASTINTER2:

                             if (hayBlancos()) transita (Estado.ESCASTINTER2);
                             else if (esParCerrado()) transita (Estado.ESCASTREAL);
                             else transita (Estado.ESIDENT);
                             break;

                         case ESCASTINT:
                             //if(lexema.length()==7)
                             // lexema=lexema.replace (" ","");
                            
                             limpiaBlancos();
                             tokenCastInt();
                             break;

                         case ESCASTREAL:

                             //if(lexema.length()==8)
                             limpiaBlancos();
                             tokenCastReal();
                             break;


                         case ESCOMENT:
                         
                                while((buffer[index]!='\n')&&(buffer[index]!='\f'))
                                //if((buffer[index]!='\f'))
                                {
                                    transita(Estado.ESCOMENT);}
                             iniciaLex();
                             linea++;
                             columna=0;
                             transita(Estado.ESINI);

                             break;

                            


                         case ESIN:

                             if (esDigito()||esLetra()||esGuionBajo()) transita(Estado.ESIDENT);
                             else tokenIn();
                             break;

                         case ESOUT:

                             if (esDigito()||esLetra()||esGuionBajo()) transita(Estado.ESIDENT);
                             else tokenOut();
                             break;

                        /* case ESIF:

                             if (esParAbierto())transita (Estado.ESIDENT);
                             else tokenIf();
                             break;
                             */
                         case ESPUNTO:
                             tokenPunto();
                             break;

                         case ESCORCHAB:
                             tokenCorchAb();
                             break;

                         case ESCORCHCER:
                             tokenCorchCer();
                             break;

                         case ESSOMB:
                             tokenSombrero();
                             break;

                         case ESAMP:
                             tokenAmpersand();
                             break;

                         case ESCOMA:
                             tokenComa();
                             break;

                         case ESEOF:

                             tokenEOF();
                             return tokens;




                     }

             }
    }
    catch(Exception e){}
    return null;
 }


private void error(){
    while ((buffer[index]!=';') || (buffer[index]=='\n')){
        index++;
     }
    boolean salto=false;
    if(buffer[index-1]=='\n'){
        salto=true;
        errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+". Amén de faltar el punto y coma final");
    }
    else errores.add("Error LEXICO. linea: "+linea+". columna: "+columna+".");
    /*for(int i=index;buffer[i]!=';';i++){
        index++;
    }*/
    tokenError();
    if(salto)
        tokenPyc();
}



    //-----------------------TOKENS-----------------------------------------

/* LAS SIGUIENTES FUNCIONES SON LAS QUE ME AÑADEN EL TOKEN CORRESPONDIENTE (EN FUNCION DE SU CATEGORIA LEXICA),
 AL ARRAYLIST DE TOKENS QUE DEVUELVE EL ANALIZADOR LEXICO, TODAS ELLAS VUELVEN A PONER EL LEXEMA A VACIO Y
 TRANSITAN AL ESTADO INICIAL. SALVO LA CORRESPONDIENTE AL TOKEN DE FIN DE FICHERO (tokenEOF())
 */

private void tokenError(){
         tokens.add(new Token(Enumerados.categoriaLexica.CLERROR,lexema));
	     iniciaLex();
	     transita(Estado.ESINI);
}

 private void tokenTreal(){
     tokens.add(new Token(Enumerados.categoriaLexica.CLTREAL,lexema));
     iniciaLex();
     transita(Estado.ESINI);
 }

 private void tokenTent(){
     tokens.add(new Token(Enumerados.categoriaLexica.CLTENT,lexema));
     iniciaLex();
     transita(Estado.ESINI);
 }

    private void tokenEOF(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLEOF,lexema));
    	iniciaLex();
    	//transita(Estado.ESINI);
    }
    private void tokenCastInt(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLCASTINT,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenCastReal(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLCASTREAL,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenIdent(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLIDENT,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenIn(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLIN,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenOut(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLOUT,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenParAbierto(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLPARAB,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenParCerrado(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLPARCER,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenOrLogico(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLOR,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenAndLogico(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLAND,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenModulo(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLMOD,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenDivision(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLDIV,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenMultiplicacion(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLMULT,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenResta(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLRES,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenSuma(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLSUM,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenDistinto(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLDIST,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenNegacion(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLNEG,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenMENIG(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLMENIG,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenMenor(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLMEN,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenMayor(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLMAY,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenMAYIG(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLMAYIG,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenComp(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLCOMP,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenAsig(){
    	tokens.add( new Token(Enumerados.categoriaLexica.CLASIG,lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }
    private void tokenReal(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLREAL, lexema));
    	iniciaLex();
    	transita(Estado.ESINI);

    }
    private void tokenInt(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLENT, lexema));
    	iniciaLex();
    	transita(Estado.ESINI);

    }
    private void tokenPyc(){
    	tokens.add(new Token(Enumerados.categoriaLexica.CLPYC, lexema));
    	iniciaLex();
    	transita(Estado.ESINI);
    }

    private void tokenIf(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLIF,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenElse(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLELSE,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
      private void tokenThen(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLTHEN,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
       private void tokenElsif(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLELSIF,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
      private void tokenEndif(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLENDIF,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenWhile(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLWHILE,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }

     private void tokenDo(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLDO,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenEndwhile(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLENDWHILE,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenRec(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLREC,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenEndrec(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLENDREC,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenTipo(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLTIPO,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenPointer(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLPOINTER,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenAlloc(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLALLOC,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenFree(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLFREE,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenFun(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLFUN,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenEnd(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLEND,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
      private void tokenReturn(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLRETURN,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenReturns(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLRETURNS,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenPunto(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLPUNTO,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenCorchAb(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLCORCHAB,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenCorchCer(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLCORCHCER,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenSombrero(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLSOMB,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
    private void tokenAmpersand(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLAMP,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenComa(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLCOMA,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }
     private void tokenNull(){
        tokens.add(new Token(Enumerados.categoriaLexica.CLNULL,lexema));
        iniciaLex();
        transita(Estado.ESINI);
    }

  //--------------------------COMPROBACIONES--------------------------------

     /* ESTAS SON LAS FUNCIONES AUXILIARES QUE HEMOS UTILIZADO PARA, FUNDAMENTALMENTE, COMPROBAR SI EL BUFFER QUE
      * NOSOTROS TENEMOS CON LOS CARACTERES, EN UNA POSICION DADA CONTIENE UN CARACTER EN PARTICULAR. POSTERIORMENTE
      * LAS USAMOS PARA TRANSITAR A UN ESTADO U OTRO EN LA FUNCION SIGTOKEN(), DE LA QUE YA HEMOS HABLADO ANTES.
      * CASO PARTICULAR EL DE LA FUNCION limpiaBlancos(), QUE ELIMINA LOS BLANCOS QUE PUDIERA HABER EN EL BUFFER.
      * ESTO ES UTIL PARA EL CASO DE LOS CASTINGS.
      */
private boolean esTabulador(){
    	if(buffer[index]=='\t') return true;
    	else return false;
    }
private void cuentaSaltos(){
    columna=1;
    linea++;
}
private boolean esIdentInt(){
	 if ((buffer[index+3]>='a' && buffer [index+3]<='z') || (buffer[index+3]>='A' && buffer [index+3]<='Z') ||
		(buffer[index+3]>='0' && buffer[index+3]<='9') || buffer[index+3]=='_') return true;
     else return false;
}
private boolean esIdentReal(){
	 if ((buffer[index+4]>='a' && buffer [index+4]<='z') || (buffer[index+4]>='A' && buffer [index+4]<='Z') ||
		(buffer[index+4]>='0' && buffer[index+4]<='9') || buffer[index+4]=='_') return true;
    else return false;
}
private void limpiaBlancos(){

     String aux="";
     for(int i=0;i<lexema.length();i++){
             if(lexema.charAt(i)!=' ')
                     aux+=lexema.charAt(i);
     }
     lexema=aux;
}
private boolean esInt(){
    if((buffer[index]=='i') && (buffer[index+1]=='n')&& (buffer[index+2]=='t')){
    	lexema+=buffer[index];
    	lexema+=buffer[index+1];
        index=index+2;
        return true;

    }
 else return false;
}
private boolean hayBlancos(){
    boolean blancos=false;
    while (buffer[index]==' '){
            blancos=true;
            index++;
    }
    if(blancos){
    	index--;
    	return true;
    }
    else return false;
}
private boolean esReal(){
    if((buffer[index]=='r' && (buffer[index+1]=='e')&& (buffer[index+2]=='a')&& (buffer[index+3]=='l'))){
    	lexema+=buffer[index];
    	lexema+=buffer[index+1];
    	lexema+=buffer[index+2];
        index=index+3;
        return true;

    }
 else return false;
}
private boolean esIn(){
    	if((buffer[index]=='i' || (buffer[index]=='I'))&&
        (buffer[index+1]=='n' || (buffer[index+1]=='N'))&&
        (buffer[index+2]==' ')){
    		this.lexema = lexema+buffer[index];
    		index++;
            return true;
        }
    	else return false;
    }
private boolean esOut(){
    	if((buffer[index]=='o' || (buffer[index]=='O'))&&
        (buffer[index+1]=='u' || (buffer[index+1]=='U'))&&
        (buffer[index+2]=='t' || (buffer[index+2]=='T'))&&
        (buffer[index+3]==' ')){
    		this.lexema = lexema+buffer[index];
    		this.lexema = lexema+buffer[index+1];
    		index=index+2;
             return true;
        }
    	else return false;
    }
private boolean esFinArchivo(){
    	if(buffer[index]=='\f') return true;
    	else return false;
    }
private boolean esFinLinea(){
    	if(buffer[index]=='\n') return true;
    	else return false;
    }
private boolean esRetornoCarro(){
    	if(buffer[index]=='\r') return true;
    	else return false;
    }
private boolean esBlanco(){
    	if(buffer[index]==' ') return true;
    	else return false;
    }
private boolean esE(){
    	if(buffer[index]=='e' || buffer[index]=='E') return true;
    	else return false;
    }
private boolean esArroba(){
    	if(buffer[index]=='@') return true;
    	else return false;
    }
private boolean esParCerrado(){
    	if(buffer[index]==')') return true;
    	else return false;
    }
private boolean esParCerrado2(){
    	if(buffer[index+2]==')') return true;
    	else return false;
    }
private boolean esParAbierto(){
    	if(buffer[index]=='(') return true;
    	else return false;
    }
private boolean esBarra(){
    	if(buffer[index]=='|') return true;
    	else return false;
    }
private boolean esAmp(){
    	if(buffer[index]=='&') return true;
    	else return false;
    }
private boolean esMod(){
    	if(buffer[index]=='%') return true;
    	else return false;
    }
private boolean esMultiplicacion(){
    	if(buffer[index]=='*') return true;
    	else return false;
    }
private boolean esDivision(){
    	if(buffer[index]=='/') return true;
    	else return false;
    }
private boolean esSuma(){
    	if(buffer[index]=='+') return true;
    	else return false;
    }
private boolean esResta(){
		/*char charMenos=buffer[index];
		String s = String.valueOf(charMenos);
		if(s.equals("-"))
		 return true;
		else*/
	if(buffer[index]=='-') return true;
	else return false;
    }
private boolean esPunto(){
    	if(buffer[index]=='.') return true;
    	else return false;
    }
private boolean esMayor(){
    	if(buffer[index]=='>') return true;
    	else return false;
    }
private boolean esExclamacion(){
    	if(buffer[index]=='!') return true;
    	else return false;
    }
private boolean esComa(){
    	if(buffer[index]==',') return true;
    	else return false;
    }
private boolean esMenor(){
    	if(buffer[index]=='<') return true;
    	else return false;
    }
private boolean esIgual(){
    	if(buffer[index]=='=') return true;
    	else return false;
    }
private boolean esIgual2(){
    	if(buffer[index+1]=='=') return true;
    	else return false;
    }
private boolean esLetra(){

    		if ((buffer[index]>='a' && buffer [index]<='z') || (buffer[index]>='A' && buffer [index]<='Z')) return true;
    		else return false;
    }
private boolean esGuionBajo(){

    		if (buffer[index]=='_') return true;
    		else return false;
    }
private boolean esDigito(){

    	if (buffer[index]>='0' && buffer[index]<='9') return true;
    	else return false;
    }
private boolean esLetra2(){

    		if ((buffer[index+1]>='a' && buffer [index+1]<='z') || (buffer[index+1]>='A' && buffer [index+1]<='Z')) return true;
    		else return false;
    }
private boolean esGuionBajo2(){

    		if (buffer[index+1]=='_') return true;
    		else return false;
    }
private boolean esBlanco2(){

    		if (buffer[index+1]==' ') return true;
    		else return false;
    }
private boolean esBlanco3(){

    		if (buffer[index+2]==' ') return true;
    		else return false;
    }
private boolean esDigito2(){

    	if (buffer[index+1]>='0' && buffer[index+1]<='9') return true;
    	else return false;
    }
private boolean esCero(){

 		if (buffer[index]=='0') return true;
		else return false;
 	}
private boolean esDigitoPos(){

    	if (buffer[index]>='1' && buffer[index]<='9') return true;
    	else return false;

    }
private boolean esPyc(){
    	if(buffer[index]==';') return true;
    	   else return false;
    }
private boolean esCorchAbierto(){

 		if (buffer[index]=='[') return true;
		else return false;
 	}
private boolean esCorchCerrado(){

 		if (buffer[index]==']') return true;
		else return false;
 	}
private boolean esSombrero(){

 		if (buffer[index]=='^') return true;
		else return false;
 	}
private boolean hayIgual(){
    	if((buffer[index-1]=='=') && buffer[index]=='='){
    		lexema+=buffer[index];
    		index++;
    		return true;
    	}
    	   else return false;
    }
private boolean hayAmp(){
    	if((buffer[index-1]=='&') && buffer[index]=='&'){
    		lexema+=buffer[index];
    		index++;
    		return true;
    	}
    	   else return false;
    }

private boolean hayMayorIgual(){
    	if((buffer[index-1]=='>') && buffer[index]=='='){
    		lexema+=buffer[index];
    		index++;
    		return true;
    	}
    	   else return false;
    }
private boolean hayDist(){
    	if((buffer[index-1]=='!') && buffer[index]=='='){
    		lexema+=buffer[index];
    		index++;
    		return true;
    	}
    	   else return false;
    }

private boolean hayMenorIgual(){
    	if((buffer[index-1]=='<') && buffer[index]=='='){
    		lexema+=buffer[index];
    		index++;
    		return true;
    	}
    	   else return false;
    }
private boolean hayBarra(){
    	if((buffer[index-1]=='|') && buffer[index]=='|'){
    		lexema+=buffer[index];
    		index++;
    		return true;
    	}
    	   else return false;
    }
private boolean sigue(){
        if (esLetra2()||esDigito2()||esGuionBajo2()||esBlanco2()) return true;
        else return false;
}
/*
private boolean esIf(){
       if(((buffer[index]=='I')||(buffer[index]=='i'))&&((buffer[index+1]=='F')||(buffer[index+1]=='f'))){
            index=index+2;
            return true;
       }
       else return false;
    }

private boolean esThen(){
    if((buffer[index]=='T' || (buffer[index]=='t'))&&
        (buffer[index+1]=='H' || (buffer[index+1]=='h'))&&
        (buffer[index+2]=='E' || (buffer[index+2]=='e'))&&
        (buffer[index+3]=='N' || (buffer[index+3]=='n'))){
        index=index+4;
        return true;
    }
    else return false;
    }

private boolean esElse(){
    if((buffer[index]=='E' || (buffer[index]=='e'))&&
        (buffer[index+1]=='L' || (buffer[index+1]=='l'))&&
        (buffer[index+2]=='S' || (buffer[index+2]=='s'))&&
        (buffer[index+3]=='E' || (buffer[index+3]=='e'))){
        index=index+4;
        return true;
    }
    else return false;
    }
private boolean esElsif(){
    if((buffer[index]=='E' || (buffer[index]=='e'))&&
        (buffer[index+1]=='L' || (buffer[index+1]=='l'))&&
        (buffer[index+2]=='S' || (buffer[index+2]=='s'))&&
        (buffer[index+3]=='I' || (buffer[index+3]=='i')) &&
        (buffer[index+4]=='F' || (buffer[index+3]=='f'))){
        index=index+5;
        return true;
    }
    else return false;
  
    }

private boolean esEndif(){
    if((buffer[index]=='E' || (buffer[index]=='e'))&&
        (buffer[index+1]=='N' || (buffer[index+1]=='n'))&&
        (buffer[index+2]=='D' || (buffer[index+2]=='d'))&&
        (buffer[index+3]=='I' || (buffer[index+3]=='i')) &&
        (buffer[index+4]=='F' || (buffer[index+3]=='f'))){
        index=index+5;
        return true;
    }
    else return false;

    }

private boolean esWhile(){
    if((buffer[index]=='W' || (buffer[index]=='w'))&&
        (buffer[index+1]=='H' || (buffer[index+1]=='h'))&&
        (buffer[index+2]=='I' || (buffer[index+2]=='i'))&&
        (buffer[index+3]=='L' || (buffer[index+3]=='l')) &&
        (buffer[index+4]=='E' || (buffer[index+3]=='e'))){
        index=index+5;
        return true;
    }
    else return false;

    }*/
private void iniciaLex(){
	lexema="";
    columna++;
}

    //-------------------GETTERS AND SETTERS-----------------------------

    public void setEstado(Estado estado) {
		this.estado = estado;
	}
	public String getLexema() {
		return lexema;
	}
	public void setLexema(String lexema) {
		this.lexema = lexema;
	}
	public ArrayList getTokens() {
		return tokens;
	}
	public void setTokens(ArrayList tokens) {
		this.tokens = tokens;
	}
	public char[] getBuffer() {
		return buffer;
	}
	public void setBuffer(char[] buffer) {
		this.buffer = buffer;
	}
	public int getIndex() {
		return index;
	}
	public void setIndex(int index) {
		this.index = index;
	}
        public String getErrores(){
             String s="";
            for(int i=0;i<errores.size();i++){
            s+=errores.get(i).toString()+"\n";
            }
            return s;
        }
        public void setErrores(ArrayList errores){
            this.errores=errores;
        }

  
}


